/**************************************************
******          Note: This file won't        ******
******     run without SDL2.dll,             ******
******     ge.dll, background.png, and       ******
******     tank.png. It's also uncommented   ******
******     as I don't fully understand the   ******
******     intricacies of SDL rendering.     ******
******     The math all solid though!        ******
**************************************************/


#include <iostream>
#include <SDL.h>
#include <string>
#include <SDL_image.h>
#include <cmath>
#include <vector>

const int SCREEN_WIDTH  = 800;
const int SCREEN_HEIGHT = 600;
const int TILE_SIZE = 50;

SDL_Window *window;
SDL_Renderer *renderer;

struct Bullet {
	double angle;
	double x;
	double y;

};
void logSDLError(std::ostream &os, const std::string &msg){
	os << msg << " error: " << SDL_GetError() << std::endl;
}
bool init() {
	if (SDL_Init(SDL_INIT_EVERYTHING) != 0){
		logSDLError(std::cout, "SDL_Init");
		return false;
	}
	if ((IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG) != IMG_INIT_PNG){
		logSDLError(std::cout, "IMG_Init");
		return false;
	}

	window = SDL_CreateWindow("Lesson 2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH,
		SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
	if (window == nullptr){
		logSDLError(std::cout, "CreateWindow");
		return false;
	}
	renderer = SDL_CreateRenderer(window, -1,
		SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
	if (renderer == nullptr){
		logSDLError(std::cout, "CreateRenderer");
		return false;
	}
	return true;
}

SDL_Surface* loadSurface(std::string path )
{
    SDL_Surface* optimizedSurface = NULL;

    SDL_Surface* loadedSurface = IMG_Load( path.c_str() );
    if( loadedSurface == NULL )
		logSDLError(std::cout, IMG_GetError());
    else
    {
        optimizedSurface = SDL_ConvertSurface( loadedSurface, SDL_GetWindowSurface(window)->format, NULL );
        if( optimizedSurface == NULL )
        {
            printf( "Unable to optimize image %s! SDL Error: %s\n", path.c_str(), SDL_GetError() );
        }

        SDL_FreeSurface( loadedSurface );
    }

    return optimizedSurface;
}

SDL_Texture* loadTexture(const std::string &file, SDL_Renderer *ren){
	SDL_Texture *texture = IMG_LoadTexture(ren, file.c_str());
	if (texture == nullptr)
		logSDLError(std::cout, "LoadTexture");
	return texture;
}


void renderTexture(SDL_Texture *tex, SDL_Renderer *ren, int x, int y, int w, int h){
	SDL_Rect renderQuad = {x, y, w, h};

	SDL_RenderCopy(ren, tex, NULL, &renderQuad);
}
void renderTexture(SDL_Texture *tex, SDL_Renderer *ren, int x, int y, double angle = 0.0, SDL_Point* center = NULL, SDL_RendererFlip flip = SDL_FLIP_NONE){
	int w, h;
	SDL_QueryTexture(tex, NULL, NULL, &w, &h);
	SDL_Rect renderQuad = {x, y, w, h};

	SDL_RenderCopyEx(ren, tex, NULL, &renderQuad, angle, center, flip);
}


void tileBackground(SDL_Texture *background, SDL_Renderer *ren) {
	int bW, bH;
	SDL_QueryTexture(background, NULL, NULL, &bW, &bH);
	int xTiles = SCREEN_WIDTH / TILE_SIZE;
	int yTiles = SCREEN_HEIGHT / TILE_SIZE;

	for (int i = 0; i < xTiles * yTiles; ++i){
		int x = i % xTiles;
		int y = i / xTiles;
		renderTexture(background, ren, x * TILE_SIZE, y * TILE_SIZE, TILE_SIZE,
			TILE_SIZE);
	}
}
int main(int argc, char **argv){


	if (!init()) return 1;


	SDL_Texture *background = loadTexture("background2.png", renderer);
	SDL_Texture *image = loadTexture("tank.png", renderer);
	if (background == nullptr || image == nullptr)
		return 4;

	SDL_RenderClear(renderer);
	SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);

	std::vector<Bullet> bullets(0);
	double angle = -90, turn = 0;
	int mov = 0;
	SDL_RendererFlip flipType = SDL_FLIP_NONE;
	int iW, iH;
	SDL_QueryTexture(image, NULL, NULL, &iW, &iH);
	double x = 0;
	double y = SCREEN_HEIGHT / 2 - iH / 2;
	renderTexture(image, renderer, x, y);

	SDL_RenderPresent(renderer);
	SDL_Event e;
	bool quit = false;
	while (!quit){



		while (SDL_PollEvent(&e)){
			if (e.type == SDL_QUIT)
				quit = true;
			if (e.type == SDL_KEYDOWN) {
				switch(e.key.keysym.sym) {
				case SDLK_LEFT:
					turn = -15;
					break;
				case SDLK_RIGHT:
					turn = 15;
					break;
				case SDLK_UP:
					mov = 1;
					break;
				case SDLK_DOWN:
					mov = -1;
					break;
				case SDLK_SPACE:
					Bullet newbullet;
					newbullet.angle = angle  * M_PI / 180;
					newbullet.x = x + iW / 2 - 5 + cos(angle * M_PI / 180) * (iW / 2) ;
					newbullet.y = y + iH / 2 - 5 + sin(angle * M_PI / 180) * (iH / 2);
					bullets.resize(bullets.size()+1);
					bullets[bullets.size()-1] = newbullet;
				}
			} else if (e.type == SDL_KEYUP) {
				switch (e.key.keysym.sym) {
				case SDLK_LEFT:
				case SDLK_RIGHT:
					turn = 0;
					break;
				case SDLK_UP:
				case SDLK_DOWN:
					mov = 0;
				}
			}
		}
		angle += turn;


		if (mov == 1) {
			x += 20 * cos(angle * M_PI / 180);
			y += 20 * sin(angle * M_PI / 180);
		} else if (mov == -1) {
			x -= 20 * cos(angle * M_PI / 180);
			y -= 20 * sin(angle * M_PI / 180);
		}

		if (x + iW >= SCREEN_WIDTH-1) x = SCREEN_WIDTH-iW;
		if (x <= 0) x = 0;
		if (y + iH >= SCREEN_HEIGHT-1) y = SCREEN_HEIGHT-iH;
		if (y <= 0) y = 0;

		SDL_RenderClear(renderer);
		renderTexture(background, renderer, 0 , 0, SCREEN_WIDTH, SCREEN_HEIGHT );
		renderTexture(image, renderer, x, y, angle+90, NULL, flipType);
		for (int i = 0; i < bullets.size(); i++) {
			SDL_Rect temp = {bullets[i].x, bullets[i].y, 10, 10};
			SDL_RenderFillRect(renderer, &temp);
			bullets[i].x += 30 * cos(bullets[i].angle);
			bullets[i].y += 30 * sin(bullets[i].angle);
			if (bullets[i].x > SCREEN_WIDTH) {bullets[i].x = SCREEN_WIDTH; bullets[i].angle = atan2(sin(bullets[i].angle), -cos(bullets[i].angle)); }
			else if (bullets[i].x < 0) {bullets[i].x *= -1; bullets[i].angle = atan2(sin(bullets[i].angle), -cos(bullets[i].angle)); }
			else if (bullets[i].y > SCREEN_HEIGHT) {bullets[i].y = 2 * SCREEN_HEIGHT - bullets[i].y; bullets[i].angle = atan2(-sin(bullets[i].angle), cos(bullets[i].angle)); }
			else if (bullets[i].y < 0) {bullets[i].y *= -1; bullets[i].angle = atan2(-sin(bullets[i].angle), cos(bullets[i].angle)); }
		}
		SDL_RenderPresent(renderer);

		SDL_Delay(50);
	}

	SDL_DestroyTexture(background);
	SDL_DestroyTexture(image);
	SDL_DestroyRenderer(renderer);
	SDL_DestroyWindow(window);
	SDL_Quit();
	return 0;
}
